#include "Cliente.h"
#include "JuegoClientImp.h"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "red_socketcliente.h"
#include "red_protocolo.h"
#include "FabricaDeTerritorios.h"
#include "Mapa.h"
#include "MapaParser.h"
#include "MensajeChat.h"
#include "MsgUtils.h"
using namespace std;

Cliente::Cliente()
{
	this->colorJugador = "";
	this->nombreJugador = "";
	this->juego = NULL;
	this->jugador = NULL;
	this->hiloDeEntrada = NULL;
}

//TODO::Arrojar excepciones.
void Cliente::conectar(string host, string puerto) {
	this->m_pSocket = new SocketCliente(host.data(),atoi(puerto.data()));
	if ((this->m_pSocket)&&(this->m_pSocket->getUtilizable())) {
		HiloDeEntrada* t_pHiloDeEntrada = new HiloDeEntrada(this->m_pSocket, this);
		t_pHiloDeEntrada->start();
	} 
	else {
		delete this->m_pSocket;
		
		this->setEstado(Cliente::ERROR_CONEXION);
		
		notifyObservers();
	}
}

void Cliente::setBajandoImagen() {
	
	this->setEstado(Cliente::DESCARGANDO_IMAGEN);
	
	notifyObservers();
}

void Cliente::setUnidoAlJuego() {
	
	this->setEstado(Cliente::UNIDO_AL_JUEGO);
	
	notifyObservers();
}

void Cliente::setBajandoMapa() {
	FabricaDeTerritorios* fabricaDeTerritorios = new FabricaDeTerritorios();
	mapa = new Mapa(fabricaDeTerritorios);
	
	this->setEstado(Cliente::DESCARGANDO_MAPA);
	
	notifyObservers();
}

void Cliente::setMapaDescargado() {
	
	this->jugador = new Jugador(nombreJugador,colorJugador);
	this->juego = new JuegoClientImp(configuracionesDelJuego.getCantidadDeJugadores(), this->mapa, this);
	this->juego->getJugadores()->push_back(jugador);
	this->setEstado(Cliente::MAPA_DESCARGADO);
	this->enviarMensaje("<getTextura/>");
	
	notifyObservers();
}

void Cliente::setTextura(string textura) {
	MsgUtils msgUtils;
	ofstream t_ofsTextura(PATH_TEXTURA, ios::binary);
	
	if (!t_ofsTextura) {
		} else {
			t_ofsTextura << msgUtils.strDecodificarBase64(textura);
			t_ofsTextura.close();
	}
	
	this->setEstado(Cliente::IMAGEN_DESCARGADA);
	
	notifyObservers();
	string mensaje = "<jugada>\n";
	mensaje += "	<unirse nombre=\""+nombreJugador+"\" color=\""+colorJugador+"\"/>\n";
	mensaje += "</jugada>";
	this->enviarMensaje(mensaje);
}

void Cliente::unirseAlJuego(string nombreJugador, string colorJugador) {
	this->nombreJugador = nombreJugador;
	this->colorJugador = colorJugador;
	this->enviarMensaje("<getMapa/>");
}

void Cliente::setConfiguracionesDelJuego(Configuraciones& configuraciones) {
	this->configuracionesDelJuego.setCantidadDeJugadores(configuraciones.getCantidadDeJugadores());
	this->configuracionesDelJuego.setNombreDelMundo(configuraciones.getNombreDelMundo());
	
	this->setEstado(Cliente::CONECTADO);
	
	notifyObservers();
}

Configuraciones* Cliente::getConfiguracionesDelJuego() {
	Configuraciones* valor;
	
	valor = &this->configuracionesDelJuego;
	
	return valor;
}

void Cliente::enviarMensajeChat(string mensaje) {
	MensajeChat mensajeChat(nombreJugador,mensaje);
	this->enviarMensaje(mensajeChat.getXML());
}

void Cliente::enviarMensaje(string mensaje) {
	std::cout << mensaje;
	Protocolo protocolo(this->m_pSocket);
	protocolo.bEnviarPaquete(mensaje);
}

JuegoClientImp* Cliente::getJuego() {
	return this->juego;
}

Jugador* Cliente::getJugador() {
	return this->jugador;
}

Mapa* Cliente::getMapa() {
	return this->mapa;
}

BuzonDeMensajes* Cliente::getBuzonDeMensajesDeChat() {
	return &mensajesDeChat;
}

BuzonDeMensajes* Cliente::getBuzonDeMensajesDeExcepcion() {
	return &mensajesDeExcepcion;
}

BuzonDeMensajes* Cliente::getBuzonDeMensajesDeSolicitud() {
	return &mensajesDeSolicitud;
}

BuzonDeMensajes* Cliente::getBuzonDeMensajesMostrarDados() {
	return &updatesDeDados;
}

BuzonDeMensajes* Cliente::getBuzonDeMensajesDeFinalizacion() {
	return &mensajesDeFinalizacion;
}

void Cliente::desconectar() {
	this->hiloDeEntrada->terminar();
}

void Cliente::join() {
	this->hiloDeEntrada->join();
	delete this->hiloDeEntrada;
}

Cliente::~Cliente()
{
	if(this->hiloDeEntrada != NULL){
		this->hiloDeEntrada->cancel();
	}
}
